#include "include/tools.h"
#include "include/config.h"

#include<string>
#include <map>
#include <memory>
#include <fcntl.h>

using namespace std;

map<string, string> MIMETYPE; 

void init_mimetype(){
    MIMETYPE.insert({"html", "text/html"});
    MIMETYPE.insert({"css", "text/css"});
    MIMETYPE.insert({"js", "text/javascript"});

    MIMETYPE.insert({"png", "image/png"});
    MIMETYPE.insert({"jpg", "image/jpeg"});
    MIMETYPE.insert({"ico", "image/x-icon"});
    MIMETYPE.insert({"webp", "image/webp"});
    MIMETYPE.insert({"gif", "image/gif"});

    MIMETYPE.insert({"wav", "audio/wav"});
    MIMETYPE.insert({"mp3", "audio/mp3"});

    MIMETYPE.insert({"mp4", "video/mp4"});
    MIMETYPE.insert({"webm", "video/webm"});

    MIMETYPE.insert({"xml", "application/xml"});
    MIMETYPE.insert({"pdf", "application/pdf"});
    MIMETYPE.insert({"zip", "application/octet-stream"});
    
}

// 智能指针回调
void closeFIle(FILE* fp){
    if(!fp) return;
    fclose(fp);
    // cout << "智能指针回调关闭了文件" << endl;
}

// 读取文件，返回文件大小
int read_file(const char* path, char *buf) {
	if (!path || !buf) {
		printf("read_file error, param is NULL \n");
		return 0;
	}
	shared_ptr<FILE> f{ fopen(path, "rb"), closeFIle }; //智能指针回调
	if (f == NULL) {
		printf("error open!\n");
		return 0;
	} 
	char buffer[4096];
	int offset = 0;
	while (1)
	{ 
		size_t count = fread(buffer, sizeof(char), 4096, f.get());
		if (count < 1)
			break;
		memcpy(buf+offset, buffer, count);
		offset += count;
	}
	return offset;
}



// 获取文件类型
string get_type_by_path(string path) {
    int n=path.size();
    if (n < 4){
        return "text/plain";
    }
    unique_ptr<string> subfix;// 智能指针
    for(int i=n-1; i>=0; i--){
        if(path[i] == '.'){
            subfix.reset( new string(path.begin() +i+1, path.begin() +n ) );  
            break;
        }
    } 
    auto it = MIMETYPE.find(*subfix);
    if( it != MIMETYPE.end()   ){ 
        return (*it).second;
    } else{ 
        return "text/plain";
    } 
}


// 静态文件
void handle_static_file(const HqHttpHead &head, HqHttpResHead &res, char *buf2  ){
    if( ! buf2 ) {
        printf("error!! handle_static_file buf2 is NULL \n");
        return;
    }
    
    // 读取文件   
    char path[128]={0};
    strcat(path, root_dir);
    strcat(path, head.path.c_str()); 
    cout << "file path:" << path << endl;

    MyFileStream *mfs = new MyFileStream(path, buf2); 
    // cout << "path2:" << path << endl;
    if( ! mfs->size ){ 
        cout << "文件不存在" << endl;
        res.resCode  = 404;
        res.resDescr = "Not Found";
        int l = sprintf(buf2, "not found ! "); 
        res.setBody(buf2,  l) ;
        res.setType("text/plain");
    }else{
        int resSize = mfs->size;
        if( mfs->size <  5000000 ){
            resSize = mfs->getnext(mfs->size);
            if( resSize != mfs->size ){
                cout << "[error] handle_static_file() 读取出错！！"<< endl;
            }
            res.setBody(buf2,  resSize) ;
            delete mfs; // 别忘记
        }else{
            // 这个文件比较大分开发送
            cout << "这个文件比较大分开发送" << endl;
            res.setHeader("Content-Length",  to_string(resSize));
            res.mfs = mfs;
        } 
        res.setType( get_type_by_path(head.path) );  
        printf("resSize=%d\n", resSize); 
    } 
}

 /*重要！设置SIGPIPE信号的行为为空，否则对端关闭之后再写数据，系统默认会关闭“进程”，直接闪退*/
void set_SIGPIPEN_NULL(){ 
    struct sigaction action; 
    action.sa_handler = [](int sig){};   //不做任何处理即可
    sigemptyset(&action.sa_mask); 
    action.sa_flags = 0; 
    sigaction(SIGPIPE, &action, NULL); 
}


// 设置非阻塞
void setNonBlock(int fd)
{
    // 通过fcntl可以改变已打开的文件性质
    int flag = fcntl(fd, F_GETFL); // 获取当前标志
    flag |= O_NONBLOCK;            // 修改为非阻塞
    fcntl(fd, F_SETFL, flag);      // set 到 fd
}

string myGetTimeString() {
	time_t nowtime;
	time(&nowtime); //获取1970年1月1日0点0分0秒到现在经过的秒数
	tm *p  = localtime(&nowtime); //将秒数转换为本地时间,年从1900算起,需要+1900,月为0-11,所以要+1
	char buf[32];
	snprintf(buf,100, "%04d:%02d:%02d %02d:%02d:%02d\n", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
	string res(buf);
	return res;
}
string myTime2String(time_t nowtime) { 
	tm *p  = localtime(&nowtime); //将秒数转换为本地时间,年从1900算起,需要+1900,月为0-11,所以要+1
	char buf[32];
	snprintf(buf,100, "%04d:%02d:%02d %02d:%02d:%02d\n", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
	string res(buf);
	return res;
}
time_t myGetTime_t() {
	time_t nowtime;
	time(&nowtime); //获取1970年1月1日0点0分0秒到现在经过的秒数
	return nowtime;
}


// 分割字符串，返回对应的vector
vector<string> split_by(string text, string space_delimiter ){  
    vector<string> words{}; 
    char buf[1500];
    strcpy(buf, text.c_str());
    char *buf2 = trim(buf, " \n\r\t");
    text = string(buf2);
    size_t pos = 0;
    while ( (pos = text.find(space_delimiter)) != string::npos) {
        words.push_back(text.substr(0, pos));
        text.erase(0, pos + space_delimiter.length());
    }
    if (text.size())
        words.push_back(text); 
    for (const auto &str : words) {
        cout << str << endl;
    }
    return words;
}
bool containchar(const char inChar,const char *srcstr)
{
    if (!srcstr) return false;
    for (size_t i = 0; i < strlen(srcstr); ++i) 
        if (inChar==srcstr[i]) 
            return true;  
    return false;
    
} 
char *trimLeft( char *src,const char* seps)
{
    if(!src) return src;
    size_t pos = 0;
    for (; pos < strlen(src); pos++)
    {
        if (!containchar(src[pos],seps))
        {
            break;
        }
    }
    if (pos>0)
    {
        char tmpStr[1024];
        strcpy(tmpStr,src+pos);
        strcpy(src,tmpStr);
    }

    return src;
}

char *trimRight( char *src,const char* seps )
{
    if(!src) return src;
    int pos =  (int)strlen(src)-1;
    for (; pos>=0 ; pos--)
    {
        if (containchar(src[pos],seps)){
            src[pos]='\0';
        }else
        {
            break;
        }
        
    }
    return src;
}

vector<char *> split(char *s, const char* seps)
{
    vector<char *> vs;
    char *resStr = NULL;
    resStr = strtok(s,seps);
    while (resStr)
    {
        vs.push_back(resStr);
        resStr = strtok(NULL,seps);
    }
    return vs;
}

char *trim( char *src,const char* seps )
{
    trimLeft(src,seps);
    trimRight(src,seps);
    return src;
}
// 输入 "?key=val&key2=value2"
std::map<std::string, std::string> splite_the_params(const char * s, const char* end){
    std::map<std::string, std::string> res;
    if(!s)
        return res;
    if(s[0] != '?') 
        return res;
    ++s;
    bool isEqual = false;
    char key[4096], value[4096];
    int i = 0, j = 0;
    while( 1 ){
        if(*s=='&' || s == end){
            if(i && j){
                std::string k(key, i);
                std::string v(value, j);
                res.insert({k, v}); 
            }else{
                printf("格式错误！在这之前：[%s] \n", s);
            }
            if(s == end)
                break;
            i = 0, j = 0;
            isEqual = false;
        }else if(*s=='='){
            isEqual = true;
        }else{
            if( ! isEqual){
                key[i++] = *s;
            }else{
                value[j++] = *s;
            }
        }
        ++s; 
    }
    return res;
}
